﻿using System;
using System.Collections.Generic;
using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif

namespace Jinndev.GameKit {

    /// <summary>
    /// 输入分发器，负责从InputManager取得输入，并分发给所有注册的监听者
    /// </summary>
    public static class InputDispatcher {

#if ENABLE_INPUT_SYSTEM
        private static Dictionary<InputActionPhase, Dictionary<string, List<Action<InputAction.CallbackContext>>>> listenerStacks = new Dictionary<InputActionPhase, Dictionary<string, List<Action<InputAction.CallbackContext>>>>();

        /// <summary>
        /// 添加监听，和RemoveListener成对使用
        /// </summary>
        public static void AddListener(string actionName, InputActionPhase phase, Action<InputAction.CallbackContext> action) {
            Dictionary<string, List<Action<InputAction.CallbackContext>>> stacks;
            if (!listenerStacks.TryGetValue(phase, out stacks)) {
                stacks = new Dictionary<string, List<Action<InputAction.CallbackContext>>>();
                listenerStacks.Add(phase, stacks);
            }
            CommonUtil.Add(stacks, actionName, action);
        }

        /// <summary>
        /// 移除监听，和AddListener成对使用
        /// </summary>
        public static void RemoveListener(string actionName, InputActionPhase phase, Action<InputAction.CallbackContext> action) {
            Dictionary<string, List<Action<InputAction.CallbackContext>>> stacks;
            if (listenerStacks.TryGetValue(phase, out stacks)) {
                bool removed = CommonUtil.Remove(stacks, actionName, action);
                if (!removed) {
                    Debug.LogError($"Action not found, name: {actionName}, phase: {phase}");
                }
            }
        }

        public static void Dispose() {
            listenerStacks.Clear();
        }

        /// <summary>
        /// 自动添加和移除监听
        /// </summary>
        public static void AutoSetListener(MonoBehaviour behaviour, string actionName, InputActionPhase phase, Action<InputAction.CallbackContext> action) {
            AutoSetListener(behaviour.gameObject, actionName, phase, action);
        }

        /// <summary>
        /// 自动添加和移除监听
        /// </summary>
        public static void AutoSetListener(GameObject gameObject, string actionName, InputActionPhase phase, Action<InputAction.CallbackContext> action) {
            AddListener(actionName, phase, action);
            DestroyCallback.Add(gameObject, () => {
                RemoveListener(actionName, phase, action);
            }, "RemoveInputListener: " + actionName + "-" + phase);
        }

        /// <summary>
        /// 触发栈顶的监听器
        /// </summary>
        public static void InvokeListener(InputAction.CallbackContext context) {
            if (listenerStacks.TryGetValue(context.phase, out var stacks)) {
                if (stacks.TryGetValue(context.action.name, out var listeners) && listeners.Count > 0) {
                    try {
                        listeners[listeners.Count - 1].Invoke(context);
                    }
                    catch (Exception e) {
                        Debug.LogException(e);
                    }
                }
            }
        }
#endif

    }

}
